#include "opendxdata.h"
static pos* DX_outputMatching(int level, DxCtrl* ctrl);
static pos* DX_outputGraph(int , DxCtrl* );
static pos* DX_outputPartition(int , char *, DxCtrl*);
static int DX_init(int , char *, DxCtrl *);
static pos *DX_readFile(int , DxCtrl* );
static void DX_printMatching(DxCtrl *);
static void DX_printGraph(DxCtrl *);
static void DX_printPartition(char* filename, DxCtrl* ctrl);
static void DX_printCoordinates(int, DxCtrl*);
static void DX_printEdges(int , DxCtrl* );
static void DX_printEdgesWeight(int , DxCtrl* ctrl);
static void DX_printVerticesWeight(int , DxCtrl* );
static void DX_printMatchedEdges(int , DxCtrl* );
static void DX_printMatchedEdgesWeight(int , DxCtrl *);
static void DX_printPartEdges(int , DxCtrl* );
static void DX_printPart(int , DxCtrl* );
static void DX_printFilePart(int ,char *, DxCtrl* );
static void DX_printField(char *object,FILE* file,...);
static void DX_printGroup(char *group_name[], int , FILE *);
static void DX_printInfo(int ,char *,FILE *);
static void DX_printProcessors(int object,DxCtrl* ctrl);

int DX_refinement(Graph *g,char* resultbase, char* coordsfile,int id
		  ,double* edgecut,double* imbalance,double* met){
  int nvtxs = 0;
  pos* new_coordinates = NULL;
  pos* ini_coords = NULL;
  pos* dumm_coords;
  char *scheme;
  DxCtrl ctrl;
  PlotGraphType *lvlg=NULL,*lvlgcopy=NULL,*refg;
  char** invert;
  int *lvlwhere = NULL ,*lvlold_where = NULL;
  int i,j;
  char buf[256];
  
  sprintf(buf,"%s.result.%d",resultbase,id);
  ctrl.tool = g->tool;
  ctrl.basename = buf;
  ctrl.coordsfile = coordsfile;
  ctrl.dim = DIM;
  ctrl.g = 0;
  ctrl.gnames = U_mallocxy(g->levels*3-2,256,char,"DX_refinement error code 1\n");
  ctrl.infos1 = U_mallocxy(g->levels*3-2,256,char,"DX_refinement error code 2\n");
  ctrl.infos2 = U_mallocxy(g->levels*3-2,256,char,"DX_refinement error code 2\n");
  ctrl.infos3 = U_mallocxy(g->levels*3-2,256,char,"DX_refinement error code 2\n");
  ctrl.f = NULL;
  ctrl.coordinates = NULL;
  ctrl.graph = g->graph;
  ctrl.grid  = g->grid;
  ctrl.obj = 1;

  CALL2VAL(g->tool,GetScheme(g->CType,g->WType,g->RType,g->CSeed,g->ISeed,g->RSeed),scheme);
  /* create info */
  sprintf(ctrl.gnames[0],"num1");
  sprintf(ctrl.infos1[0],"%s",scheme);
  sprintf(ctrl.infos2[0],"result %d final before et",id);
  sprintf(ctrl.infos3[0],"[edgecut:%d] [imbalance:%f]",(int)edgecut[1],imbalance[1]);
  sprintf(ctrl.gnames[1],"num2");
  sprintf(ctrl.infos1[1],"%s",scheme);
  sprintf(ctrl.infos2[1],"result %d final before et (before refinement)",id);
  sprintf(ctrl.infos3[1],"[edgecut:%d] [imbalance:%f]",(int)edgecut[2],imbalance[2]);
  sprintf(ctrl.gnames[2],"num0");
  sprintf(ctrl.infos1[2],"%s",scheme);
  sprintf(ctrl.infos2[2],"result %d final after et",id);
  sprintf(ctrl.infos3[2],"[edgecut:%d] [imbalance:%f]",(int)edgecut[0],imbalance[0]);
  for(i=0;i<g->levels-2;i++){
    sprintf(ctrl.gnames[3*i+3],"num%d",3*i+3);
    sprintf(ctrl.infos1[3*i+3],"%s",scheme);
    sprintf(ctrl.infos2[3*i+3],"result %d lvl %d coarsen",id,i+1);
    sprintf(ctrl.infos3[3*i+3],"[edgecut:%d] [imbalance:%f]",
	    (int)edgecut[i+2],imbalance[i+2]);
    sprintf(ctrl.gnames[3*i+4],"num%d",3*i+4);
    sprintf(ctrl.infos1[3*i+4],"%s",scheme);
    if(i == g->levels-3)
      sprintf(ctrl.infos2[3*i+4],"result %d initial partition coarsen",id);
    else
      sprintf(ctrl.infos2[3*i+4],"result %d lvl %d coarsen (before refinement)",id,i+1);
    sprintf(ctrl.infos3[3*i+4],"[edgecut:%d] [imbalance:%f]",
	    (int)edgecut[i+3],imbalance[i+3]);
    sprintf(ctrl.gnames[3*i+5],"num%d",3*i+5);
    sprintf(ctrl.infos1[3*i+5],"%s",scheme);
    sprintf(ctrl.infos2[3*i+5],"result %d lvl %d",id,i+1);
    sprintf(ctrl.infos3[3*i+5],"[edgecut:%d] [imbalance:%f]",
	  (int)edgecut[i+2],imbalance[i+2]);
  }
  sprintf(ctrl.gnames[3*i+3],"num%d",3*i+3);
  sprintf(ctrl.infos1[3*i+3],"%s",scheme);
  sprintf(ctrl.infos2[3*i+3],"result %d initial partition",id);
  sprintf(ctrl.infos3[3*i+3],"[edgecut:%d] [imbalance:%f]",(int)edgecut[i+2],imbalance[i+2]);
  
  printf(".");fflush(stdout);
  nvtxs = g->graph->nvtxs;
  lvlg = g->graph;
  /* final results */
  /* for modulo 3 operations start with coarsen refinement */
  lvlg = lvlg->child;
  printf(".");fflush(stdout);
  dumm_coords = DX_outputPartition(1, NULL, &ctrl);
  U_free("DX_refinement error code 5\n",&dumm_coords,LEND);
  /* duplicate graph to see what is refined */
  lvlgcopy = PLIBG_Init();
  PLIBG_Copy(lvlgcopy, lvlg);
  PLIBG_Insert(lvlg,lvlgcopy);
  ctrl.g++;
  lvlg = lvlgcopy;
  ctrl.graph = lvlg;
  printf(".");fflush(stdout);
  new_coordinates = DX_outputPartition(1, NULL, &ctrl);
  ini_coords = ctrl.coordinates;
  ctrl.g++;
  /* this one become the ref for uncoarsen refinement (finer graph)*/
  refg = lvlg;
  /* final after exectime load balancing */
  ctrl.graph = g->graph;
  printf(".");fflush(stdout);
  dumm_coords = DX_outputPartition(1, NULL, &ctrl);
  U_free("DX_refinement error code 5\n",&dumm_coords,LEND);
  ctrl.coordinates = new_coordinates;
  ctrl.g++;

  /* for each level */
  refg = lvlg;
  for(i=2;i<g->levels-1;i++){
    /* coarsen partition */
    lvlg = lvlg->child;
    ctrl.graph = lvlg;
    printf(".");fflush(stdout);
    new_coordinates = DX_outputPartition(1, NULL, &ctrl);
    ctrl.g++;
    /* duplicate graph to see what is refined */
    lvlgcopy = PLIBG_Init();
    PLIBG_Copy(lvlgcopy, lvlg);
    PLIBG_Insert(lvlg,lvlgcopy);
    ctrl.graph = lvlgcopy;
    lvlg = lvlgcopy;
    printf(".");fflush(stdout);
    dumm_coords = DX_outputPartition(1, NULL, &ctrl);
    U_free("DX_refinement error code 5\n",&dumm_coords,LEND);
    ctrl.g++;
    
    /* uncoarsen partition */    
    /* get data */
    lvlwhere = PLIBG_BuildWhere(lvlg,refg);
    ctrl.graph = refg;
    U_free("DX_refinement error code 6\n",&(ctrl.coordinates),LEND);
    ctrl.coordinates  = ini_coords;
    /* print */
    printf(".");fflush(stdout);
    dumm_coords = DX_outputPartition(1, NULL, &ctrl);
    U_free("DX_refinement error code 7\n",&dumm_coords,LEND);
    ctrl.g++;

    /* undo changes */
    PLIBG_SwitchWhere(refg,lvlwhere,&lvlold_where);
    U_free("DX_refinement error code 8\n",&lvlold_where,LEND);
    ctrl.coordinates = new_coordinates;
  }
  /* initial partition */
  /* coarsen partition */
  lvlg = lvlg->child;
  ctrl.graph = lvlg;
  printf(".");fflush(stdout);
  dumm_coords = DX_outputPartition(1, NULL, &ctrl);
  U_free("DX_refinement error code 7\n",&dumm_coords,LEND);
  ctrl.g++;
  /* coarsen initial before refinement */
  lvlgcopy = lvlg->child;
  ctrl.graph = lvlgcopy;
  printf(".");fflush(stdout);
  dumm_coords = DX_outputPartition(1, NULL, &ctrl);
  U_free("DX_refinement error code 7\n",&dumm_coords,LEND);
  ctrl.g++;
  /* initial uncoarsen after refinement*/
  lvlwhere = PLIBG_BuildWhere(lvlg,refg);
  ctrl.graph = refg;
  U_free("DX_refinement error code 6\n",&(ctrl.coordinates),LEND);
  ctrl.coordinates  = ini_coords;
  /* print */
  printf(".");fflush(stdout);
  dumm_coords = DX_outputPartition(1, NULL, &ctrl);
  U_free("DX_refinement error code 7\n",&dumm_coords,LEND);
  ctrl.g++;
  /* undo changes */
  PLIBG_SwitchWhere(refg,lvlwhere,&lvlold_where);
  U_free("DX_refinement error code 8\n",&lvlold_where,LEND);
  /* initial uncoarsen before refinement*/
  lvlwhere = PLIBG_BuildWhere(lvlgcopy,refg);
  ctrl.graph = refg;
  /* print */
  printf(".\n");fflush(stdout);
  dumm_coords = DX_outputPartition(1, NULL, &ctrl);
  U_free("DX_refinement error code 7\n",&dumm_coords,LEND);
  ctrl.g++;
  /* undo changes */
  PLIBG_SwitchWhere(refg,lvlwhere,&lvlold_where);
  U_free("DX_refinement error code 8\n",&lvlold_where,LEND);

  /* invert results */
  invert = U_malloc(3*g->levels,char *,"DX_refinement error code 8\n");
  /* for modulo 3 operation */
  invert[0] = invert[1] = invert[2] = ctrl.gnames[ctrl.g-1];
  /* invert order */
  for(i=ctrl.g-2,j=3;i>=0;i--,j++)
    invert[j]=ctrl.gnames[i];
  DX_printGroup(invert, ctrl.g+2 , ctrl.f);
  fclose(ctrl.f);
  U_free("DX_refinement error code 10\n",&(ctrl.gnames),&(ctrl.infos1),
	   &(ctrl.infos2),&(ctrl.infos3),&invert,&scheme,
	 &(ctrl.coordinates),LEND);
  return 1;
}
int DX_matching(Graph *g,char *filename, char* coordsfile){
  int i;
  pos* new_coordinates = NULL;
  PlotGraphType *lvl_graph = g->graph;
  char *scheme;
  DxCtrl ctrl;
  CALL2VAL(g->tool,GetScheme(g->CType,g->WType,g->RType,-1,-1,-1),scheme);
  ctrl.g = 0;
  ctrl.tool = g->tool;
  ctrl.basename = filename;
  ctrl.coordsfile = coordsfile;
  ctrl.dim = DIM;
  ctrl.gnames = U_mallocxy(g->levels+1,256,char,"DX_refinement error code 1\n");
  ctrl.infos1 = U_mallocxy(g->levels+1,256,char,"DX_refinement error code 2\n");
  ctrl.infos2 = U_mallocxy(g->levels+1,256,char,"DX_refinement error code 2\n");
  ctrl.f = NULL;
  ctrl.coordinates = NULL;
  ctrl.graph = g->graph;
  ctrl.grid  = g->grid;
  ctrl.obj = 1;
  /* build infos */
  for(i=0;i<=g->levels;i++){
    sprintf(ctrl.gnames[i],"lvl%d",i+1);
    sprintf(ctrl.infos1[i],"%s",scheme);
    sprintf(ctrl.infos2[i],"%s level %d",filename,i+1);
  }
  
  /* matching levels */
  for(i=0;i<=g->levels;i++){
    ctrl.graph = lvl_graph;
    //new_coordinates = DX_outputMatching(i+1, &ctrl);
    new_coordinates = DX_outputGraph(i+1, &ctrl);
    ctrl.g++;
    U_free("DX_all error code 1\n",&(ctrl.coordinates),LEND);
    ctrl.coordinates = new_coordinates;
    lvl_graph = lvl_graph->child;
  }
  /* final matching */
  //DX_outputGraph(i+1, &ctrl);
  //ctrl.g++;
  DX_printGroup(ctrl.gnames, ctrl.g , ctrl.f);
  U_free("DX_matching error code 4\n",&(ctrl.gnames),&(ctrl.infos1),
	   &(ctrl.infos2),&(ctrl.coordinates),&scheme,LEND);
  fclose(ctrl.f);
  ctrl.f = NULL;
  return 1;
}


pos* DX_outputMatching(int level, DxCtrl* ctrl){
  pos *new_coordinates;
  int i;
  char buffer[256];
  int nvtxs = 0;
  int *match = NULL;
  int *map = NULL;
  PlotGraphType *test_last;

  test_last = ctrl->graph;
  test_last = test_last->child;
  if(test_last != NULL){
    nvtxs = ctrl->graph->nvtxs;
    match = ctrl->graph->match;
    map   = ctrl->graph->map;
  }

  if(ctrl->g == -1 || ctrl->f == NULL){
    if(ctrl->g == -1){
      sprintf(buffer,"%s.coarse.level.%d.dx",ctrl->basename,level);
      WARNING((DX_init(level, buffer, ctrl) == 0,"DX_outputMatching error : error in DX_outputGraph\n"),NULL);
    }else{
      sprintf(buffer,"%s.dx",ctrl->basename);
      WARNING((DX_init(level, buffer, ctrl) == 0,"DX_outputMatching error : error in DX_outputGraph\n"),NULL);
    }
  }

  /* print mathing */
  DX_printMatching(ctrl);
  /* compute new coordinates */
  new_coordinates = U_malloc(nvtxs,pos,"DX_outputMatching error : cannot allocate memory\n");
  if(test_last != NULL){
    for(i=0;i<nvtxs;i++){
      if(i<match[i]){
	new_coordinates[map[i]].x=((ctrl->coordinates)[i].x+(ctrl->coordinates)[match[i]].x)/2;
	if(ctrl->dim > 1)
	  new_coordinates[map[i]].y=((ctrl->coordinates)[i].y+(ctrl->coordinates)[match[i]].y)/2;
	if(ctrl->dim > 2)
	  new_coordinates[map[i]].z=((ctrl->coordinates)[i].z+(ctrl->coordinates)[match[i]].z)/2;
      }else if(i == match[i]){
	new_coordinates[map[i]] = (ctrl->coordinates)[i];
      }
    }
    if(ctrl->g == -1){
      fclose(ctrl->f);
      ctrl->f = NULL;
    }
    U_free("DX_outputMatching error code 1\n",&map,&match,LEND);
  }
  return new_coordinates;
}

pos* DX_outputGraph(int level, DxCtrl* ctrl){
  pos *new_coordinates;
  int i;
  char buffer[256];
  int nvtxs = 0;
  int *match = NULL;
  int *map = NULL;
  PlotGraphType *test_last;

  test_last = ctrl->graph;
  test_last = test_last->child;
  if(test_last != NULL){
    nvtxs = ctrl->graph->nvtxs;
    match = ctrl->graph->match;;
    map   = ctrl->graph->map;;
  }
  
  if(ctrl->g == -1 || ctrl->f == NULL){
    if(ctrl->g == -1){
      sprintf(buffer,"%s.coarse.level.%d.dx",ctrl->basename,level);
      WARNING((DX_init(level,buffer,ctrl) == 0,"DX_outputGraph error : error in DX_init\n"),0);
    }else{
      sprintf(buffer,"%s.dx",ctrl->basename);
      WARNING((DX_init(level,buffer,ctrl) == 0,"DX_outputGraph error : error in DX_init\n"),0);
    }
  }
  
  /* print mathing */
  DX_printGraph(ctrl);

  if(ctrl->g == -1){
    fclose(ctrl->f);
    ctrl->f = NULL;
  }

  /* compute new coordinates */
  new_coordinates = U_malloc(nvtxs,pos,"DX_outputMatching error : cannot allocate memory\n");
  if(test_last != NULL){
    for(i=0;i<nvtxs;i++){
      if(i<match[i]){
	new_coordinates[map[i]].x=((ctrl->coordinates)[i].x+(ctrl->coordinates)[match[i]].x)/2;
	if(ctrl->dim > 1)
	  new_coordinates[map[i]].y=((ctrl->coordinates)[i].y+(ctrl->coordinates)[match[i]].y)/2;
	if(ctrl->dim > 2)
	  new_coordinates[map[i]].z=((ctrl->coordinates)[i].z+(ctrl->coordinates)[match[i]].z)/2;
      }else if(i == match[i]){
	new_coordinates[map[i]] = (ctrl->coordinates)[i];
      }
    }
  }
  return new_coordinates;
}

pos* DX_outputPartition(int level, char *file, DxCtrl* ctrl){
  FILE* fp;
  char buffer[256];
  int i = 1;
  pos *new_coordinates;
  int nvtxs = 0;
  int *match = NULL;
  int *map = NULL;
  PlotGraphType *test_last;

  test_last = ctrl->graph;
  test_last = test_last->child;
  if(test_last != NULL){
    nvtxs = ctrl->graph->nvtxs;
    match = ctrl->graph->match;
    map   = ctrl->graph->map;
  }

  if(ctrl->g == -1 || ctrl->f == NULL){
    if(ctrl->g == -1){
      do{
	sprintf(buffer,"%s.part.%d.dx",ctrl->basename,i++);
	fp = fopen(buffer,"r");
      }while(fp != NULL && fclose(fp)!=EOF);
    }else{
      sprintf(buffer,"%s.dx",ctrl->basename);
    }
    WARNING((DX_init(level,buffer,ctrl) == 0,"DX_outputPartition error : error in DX_init\n"),0);
  }
  
  /* print partition */
  DX_printPartition(file,ctrl);

  if(ctrl->g == -1){
    fclose(ctrl->f);
    ctrl->f = NULL;
  }

  /* compute new coordinates */
  new_coordinates = U_malloc(nvtxs,pos,"DX_outputMatching error : cannot allocate memory\n");
  if(test_last != NULL){
    for(i=0;i<nvtxs;i++){
      if(i<match[i]){
	new_coordinates[map[i]].x=((ctrl->coordinates)[i].x+(ctrl->coordinates)[match[i]].x)/2;
	if(ctrl->dim > 1)
	  new_coordinates[map[i]].y=((ctrl->coordinates)[i].y+(ctrl->coordinates)[match[i]].y)/2;
	if(ctrl->dim > 2)
	  new_coordinates[map[i]].z=((ctrl->coordinates)[i].z+(ctrl->coordinates)[match[i]].z)/2;
      }else if(i == match[i]){
	new_coordinates[map[i]] = (ctrl->coordinates)[i];
      }
    }    
  }
  return new_coordinates;
}

int DX_init(int level, char *f_dx, DxCtrl *ctrl){
  FILE *fp;
  int nvtxs = 0;

  nvtxs = ctrl->graph->nvtxs;

  /* error checking on dim */
  WARNING((ctrl->dim<0 || ctrl->dim>3,"DX_init error : dim = %d must be 1, 2 ou 3\n",ctrl->dim),0);

  /* if coordinates not assigned read coordinates file */
  if(ctrl->coordinates == NULL)
    WARNING(((ctrl->coordinates = DX_readFile(nvtxs,ctrl)) == NULL,"DX_init error : error in DX_readFile\n"),0);

  /* open output file */
  WARNING(((fp=fopen(f_dx,"w"))==NULL,"DX_init error : cannot open file %s\n",f_dx),0);

  ctrl->f = fp;
  return 1;
}

pos *DX_readFile(int nnodes, DxCtrl* ctrl){
  FILE *fp;
  pos *coordinates;
  int i = 0;
  char buffer[256];
  float dummy;

  /* allocate memory */
  coordinates = U_malloc(nnodes,pos,"DX_readFile error code 1\n");

  WARNING(((fp=fopen(ctrl->coordsfile,"r"))==NULL,"DX_readFile error : cannot open coordinate file %s\n",ctrl->coordsfile),NULL);
  WARNING((fgets(buffer,255,fp) == NULL,"DX_readFile error : cannot read line %d\n",i+1),NULL);
  ctrl->dim = sscanf(buffer,"%g %g %g",&dummy,&dummy,&dummy);
  rewind(fp);

  for(i=0;i<nnodes;i++){
    WARNING((fgets(buffer,255,fp) == NULL,"DX_readFile error : cannot read line %d\n",i+1),NULL);

    switch(ctrl->dim){
    case 1:
      WARNING((sscanf(buffer,"%g",&(coordinates[i].x))!=1,"DX_readFile error : line %d is not correct\n",i+1),NULL);
      break;
    case 2:
      WARNING((sscanf(buffer,"%g %g",&(coordinates[i].x),&(coordinates[i].y))!=2,"DX_readFile error : line %d is not correct\n",i+1),NULL);
      break;
    case 3:
      WARNING((sscanf(buffer,"%g %g %g",&(coordinates[i].x),&(coordinates[i].y),&(coordinates[i].z))!=3,"DX_readFile error : line %d is not correct\n",i+1),NULL);
      break;
    }
  }

  fclose(fp);
  return coordinates;
}

void DX_printMatching(DxCtrl *ctrl){
  char *group_name[1];
  int obj = 1;

  if(ctrl->g != -1){
    obj = ctrl->obj;
    ctrl->obj += 8;
  }else
    obj = 1;

  fprintf(ctrl->f,"# file for openDX generated by DX_printMatching\n");
  DX_printCoordinates(obj, ctrl);
  DX_printEdges(obj + 1, ctrl);
  DX_printVerticesWeight(obj + 2, ctrl);
  DX_printEdgesWeight(obj + 3, ctrl);
  DX_printMatchedEdges(obj + 4, ctrl);
  DX_printMatchedEdgesWeight(obj + 5, ctrl);
  
  /*DX_printField("vwgt",obj,obj + 1,obj + 2, ctrl->f);
  DX_printField("ewgt",obj,obj + 1,obj + 3, ctrl->f);
  group_name[1]="ewgt";
  DX_printField("matching",obj,obj + 4,obj + 5, ctrl->f);
  group_name[2]="matching";*/
  
  if(ctrl->g == -1){
    DX_printField("hehe",ctrl->f,"positions",obj,"connections",obj+1,"vwgt",
		       obj + 2,"ewgt",obj + 3,"me",obj + 4,"mewgt",obj + 5,LEND);
    group_name[0]="hehe";
    DX_printGroup(group_name,1,ctrl->f);
  }else{
    DX_printInfo(obj + 6,ctrl->infos1[ctrl->g],ctrl->f);
    DX_printInfo(obj + 7,ctrl->infos2[ctrl->g],ctrl->f);
    DX_printField(ctrl->gnames[ctrl->g],ctrl->f,"positions",obj,"connections",
		       obj+1,"vwgt",obj + 2,"ewgt",obj + 3,"me",obj + 4,
		       "mewgt",obj + 5,"info1",obj + 6,"info2",obj+7,LEND);
  }
}

void DX_printGraph(DxCtrl *ctrl){
  char *group_name[1];
  int obj = 1;
  
  if(ctrl->g != -1){
    obj = ctrl->obj;
    ctrl->obj += 6;
  }else
    obj = 1;

  fprintf(ctrl->f,"# file for openDX generated by DX_printGraph\n");
  DX_printCoordinates(obj, ctrl);
  DX_printEdges(obj + 1, ctrl);
  DX_printVerticesWeight(obj + 2, ctrl);
  DX_printEdgesWeight(obj + 3, ctrl);
  /*DX_printField("vwgt",obj,obj + 1,obj + 2, ctrl->f);
  group_name[0]="vwgt";
  DX_printField("ewgt",obj,obj + 1,obj + 3, ctrl->f);
  group_name[1]="ewgt";
  DX_printGroup(group_name,2,ctrl->f);*/

  if(ctrl->g == -1){
    DX_printField("hehe",ctrl->f,"positions",obj,"connections",obj+1,
		       "vwgt",obj + 2,"ewgt",obj + 3,LEND);
    group_name[0]="hehe";
    DX_printGroup(group_name,1,ctrl->f);
  }else{
    DX_printInfo(obj + 4,ctrl->infos1[ctrl->g],ctrl->f);
    DX_printInfo(obj + 5,ctrl->infos2[ctrl->g],ctrl->f);
    DX_printField(ctrl->gnames[ctrl->g],ctrl->f,"positions",obj,"connections",
		       obj+1,"vwgt",obj + 2,"ewgt",obj + 3,"info1",obj + 4,"info2",
		       obj+5,LEND);
  }
}

void DX_printPartition(char* filename, DxCtrl* ctrl){
  char *group_name[1];
  int obj = 1;

  if(ctrl->g != -1){
    obj = ctrl->obj;
    ctrl->obj += 7;
  }else
    obj = 1;
  
  fprintf(ctrl->f,"# file for openDX generated by DX_printGraph\n");
  DX_printCoordinates(obj, ctrl);
  DX_printPartEdges(obj + 1, ctrl);
  if(filename == NULL)
    DX_printPart(obj + 2, ctrl);
  else
    DX_printFilePart(obj + 2, filename, ctrl);
  DX_printProcessors(obj + 3, ctrl);
  if(ctrl->g == -1){
    DX_printField("partition",ctrl->f,"positions",obj,"connections",obj+1,
		       "data",obj + 2,"procs",obj + 3,LEND);
    group_name[0]="partition";
    DX_printGroup(group_name,1,ctrl->f);
  }else{
    DX_printInfo(obj + 4,ctrl->infos1[ctrl->g],ctrl->f);
    DX_printInfo(obj + 5,ctrl->infos2[ctrl->g],ctrl->f);
    DX_printInfo(obj + 6,ctrl->infos3[ctrl->g],ctrl->f);
    DX_printField(ctrl->gnames[ctrl->g],ctrl->f,"positions",obj,"connections",obj+1,
		  "data",obj + 2,"procs",obj+3,"info1",obj+4,"info2",obj+5,
		  "info3",obj+6,LEND);
  }
}

void DX_printCoordinates(int object, DxCtrl *ctrl){
  int i,nvtxs = 0;
  FILE* file = ctrl->f;
  PlotGraphType* g = ctrl->graph;
  pos* coordinates = ctrl->coordinates;
  
  nvtxs = g->nvtxs;

  fprintf(file,"# object %d : coordinates\n",object);
  fprintf(file,"object %d class array type float rank 1 shape %d items %d data follows\n",object,ctrl->dim,nvtxs);
  for(i=0;i<nvtxs;i++){
    switch(ctrl->dim){
    case 1:
      fprintf(file,"%g\n",coordinates[i].x);
      break;
    case 2:
      fprintf(file,"%g %g\n",coordinates[i].x,coordinates[i].y);
      break;
    case 3:
      fprintf(file,"%g %g %g\n",coordinates[i].x,coordinates[i].y,coordinates[i].z);
      break;
    }
  }
  fprintf(file,"#\n");
}

void DX_printEdges(int object, DxCtrl* ctrl){
  int i,j,jstart,jend;
  int nvtxs = 0, nedges = 0;
  int *edges;
  FILE* file=ctrl->f;
  PlotGraphType* g = ctrl->graph;

  nvtxs  = g->nvtxs;
  nedges = g->nedges/2;

  edges = U_malloc(nedges+1,int,"DX_printEdges error code 1\n");

  fprintf(file,"# object %d : edges\n",object);
  fprintf(file,"object %d class array type int rank 1 shape 2 items %d data follows\n",object,2 * nedges);
  for(i=0;i<nvtxs;i++){

    jstart = g->adjidx[i];
    jend   = g->adjidx[i+1];

    for(j=jstart;j<jend;j++)
      fprintf(file,"%d %d\n",i,g->adjncy[j]);
  }

  U_free("DX_printEdges error code 1\n",&edges,LEND);
    
  fprintf(file,"#\nattribute \"element type\" string \"lines\"\n");
  fprintf(file,"attribute \"ref\" string \"positions\"\n#\n");
}

void DX_printVerticesWeight(int object, DxCtrl* ctrl){
  int i;
  int *vwgt = NULL;
  FILE* file = ctrl->f;
  PlotGraphType* g=ctrl->graph;

  vwgt = g->vwgt;  

  fprintf(file,"# object %d : data\n",object);
  fprintf(file,"object %d class array type int rank 0 items %d data follows\n",object,g->nvtxs);
  
  for(i=0;i<g->nvtxs;i++)
    fprintf(file,"%d\n",vwgt[i]);

  fprintf(file,"#\nattribute \"dep\" string \"positions\"\n#\n");

}

void DX_printEdgesWeight(int object, DxCtrl* ctrl){
  int i,j,jstart,jend;
  int nvtxs = 0;
  int nedges = 0;
  double* ewgt;
  FILE* file = ctrl->f;
  PlotGraphType*g = ctrl->graph;
  
  nvtxs  = g->nvtxs;
  nedges = g->nedges/2;

  ewgt = U_malloc(nedges + 1,double,"DX_printEdgesWeight error code 1\n");

  fprintf(file,"# object %d : edges weight\n",object);
  fprintf(file,"object %d class array type int rank 0 items %d data follows\n",object,nedges*2);
  for(i=0;i<nvtxs;i++){
    jstart = g->adjidx[i];
    jend   = g->adjidx[i+1];
    for(j=jstart;j<jend;j++){
      fprintf(file,"%d\n",g->adjwgt[j]);
    }
  }
  fprintf(file,"#\nattribute \"dep\" string \"connections\"\n#\n");

  U_free("DX_printEdgesWeight error code 1\n",&ewgt,LEND);
}

void DX_printMatchedEdges(int object, DxCtrl* ctrl){
  int nvtxs = 0;
  int *match = NULL;
  int i,nedges=0;
  FILE *file=ctrl->f;
  PlotGraphType* g = ctrl->graph;

  nvtxs = g->nvtxs;
  match = g->match;

  /* count matched edges */
  for(i=0;i<nvtxs;i++){
    if(match[i]!=i)
      nedges++;
  }
  
  fprintf(file,"# object %d : matching\n",object);
  fprintf(file,"object %d class array type int rank 1 shape 2 items %d data follows\n",object,nedges/2);
  for(i=0;i<nvtxs;i++){
    if(i>match[i])
      fprintf(file,"%d %d\n",i,match[i]);
  }
  fprintf(file,"#\nattribute \"element type\" string \"lines\"\n");
  fprintf(file,"attribute \"ref\" string \"positions\"\n#\n");

  U_free("DX_printMatchedEdges error code 1\n",&match,LEND);
}

void DX_printMatchedEdgesWeight(int object, DxCtrl *ctrl){
  int nvtxs = 0;
  int *match = NULL;
  int i,j,jstart,jend,nedges=0;
  FILE* file=ctrl->f;
  PlotGraphType* g=ctrl->graph;

  nvtxs = g->nvtxs;
  match = g->match;

  /* count matched edges */
  for(i=0;i<nvtxs;i++){
    if(match[i]!=i)
      nedges++;
  }

  fprintf(file,"# object %d : matched edges weight\n",object);
  fprintf(file,"object %d class array type int rank 0 items %d data follows\n",object,nedges/2);
  for(i=0;i<nvtxs;i++)
    if(i>match[i]){

      jstart = g->adjidx[i];
      jend   = g->adjidx[i+1];

      for(j=jstart;j<jend;j++){
	if(g->adjncy[j] == match[i]){
	  fprintf(file,"%d\n",g->adjwgt[j]);
	  break;
	}
      }      
    }

  fprintf(file,"#\nattribute \"dep\" string \"connections\"\n#\n");

  U_free("DX_printMatchedEdgesWeight error code 1\n",&match,LEND);
}

void DX_printPartEdges(int object, DxCtrl* ctrl){
  PlotGraphType*g = ctrl->graph;
  int
    i,j,
    nvtxs = 0,
    nedges= 0,
    pedges = 0,
    none = 0,
    *edges;
  FILE* file = ctrl->f;

  nvtxs  = g->nvtxs;
  nedges = g->nedges/2;

  edges = U_malloc(nedges+1,int,"DX_printPartitionEdges error code 1\n");
  
  fprintf(file,"# object %d : edges\n",object);

  /* count edges */
  for(i=0;i<nvtxs;i++){
    edges = PLIBG_PartEdges(g,i,edges);
    pedges += edges[0];
  }

  if(pedges == 0)
    pedges = none = 1;

  fprintf(file,"object %d class array type int rank 1 shape 2 items %d data follows\n",object,pedges);

  if(none == 1){
    fprintf(file,"0 0\n");
  }else{
    /* print edges */
    for(i=0;i<nvtxs;i++){
      edges = PLIBG_PartEdges(g,i,edges);
      pedges = edges[0];
      for(j=1;j<=pedges;j++)
	fprintf(file,"%d %d\n",i,edges[j]);
    }  
  }
  fprintf(file,"#\nattribute \"element type\" string \"lines\"\n");
  fprintf(file,"attribute \"ref\" string \"positions\"\n#\n");
  U_free("DX_printPartitionEdges error code 2\n",&edges,LEND);
}

void DX_printPart(int object, DxCtrl* ctrl){
  FILE* file=ctrl->f;
  PlotGraphType* g = ctrl->graph;
  int 
    i,
    nvtxs = 0,
    *where = NULL;

  nvtxs = g->nvtxs;
  where = g->pro;

  fprintf(file,"# object %d : data\n",object);
  fprintf(file,"object %d class array type int rank 0 items %d data follows\n",object,nvtxs);
  for(i=0;i<nvtxs;i++)
    fprintf(file,"%d\n",where[i]);
  fprintf(file,"attribute \"dep\" string \"positions\"\n#\n");

}

void DX_printFilePart(int object, char *filename, DxCtrl* ctrl){
  FILE* file = ctrl->f;
  PlotGraphType* g = ctrl->graph;
  int nvtxs = 0;
  nvtxs = g->nvtxs;

  fprintf(file,"# object %d : data\n",object);
  fprintf(file,"object %d class array type int rank 0 items %d\n",object,nvtxs);
  fprintf(file,"data file %s,0\n#\n",filename);
  fprintf(file,"attribute \"dep\" string \"positions\"\n#\n");
}

void DX_printField(char *object,FILE* file,...){
  va_list alist;
  char* component;
  int id;

  fprintf(file,"# object %s : field\n",object);
  fprintf(file,"object \"%s\" class field\n",object);
  va_start(alist, file);
  while((component = va_arg(alist, char*)) != (char*)LEND){
    id = va_arg(alist, int);
    fprintf(file,"component \"%s\" value %d\n",component,id);
  }
  fprintf(file,"#\n");
  va_end(alist);
}
void DX_printGroup(char *group_name[], int nb, FILE *file){
  int i;
  fprintf(file,"object \"default\" class group\n");
  for(i=0;i<nb;i++){
    fprintf(file,"member %d value \"%s\"\n",i,group_name[i]);
  }
  fprintf(file,"end\n");
}
void DX_printInfo(int object,char *info,FILE *file){
  fprintf(file,"object %d string \"%s\"\n",object,info);
}
void DX_printProcessors(int object,DxCtrl* ctrl){
  int nbproc = 0;
  int i;
  
  nbproc = PLIBG_NbProc(ctrl->graph);
  fprintf(ctrl->f,"# object %d : data\n",object);
  fprintf(ctrl->f,"object %d class array type string rank 1 shape 8 items %d data follows\n",object,nbproc);
  for(i=0;i<nbproc;i++)
    fprintf(ctrl->f,"\"proc %2d\"\n",i+1);
  fprintf(ctrl->f,"#\n");
}
